
#include <WiFi.h>
#include "Http.h"
#include <WiFiMulti.h>
#include <HTTPClient.h>
#include <Preferences.h>
#include "ActionCtrl.h"
#include "config.h"
#include "global.h"
#include "WiFiClientSecure.h"
#include "List.h"
#include "Log.h"

WiFiMulti wifi;

int count = 0;
extern String ssid;
extern String password;

// 设置静态IP配置
IPAddress local_IP(192, 168, 0, 180); // 本地IP地址
IPAddress gateway(192, 168, 0, 1);    // 网关
IPAddress subnet(255, 255, 255, 0);   // 子网掩码
IPAddress dns1(192, 168, 0, 1);       // DNS服务器


List<Http> cacheHttpList;
 

const char* ca =   "-----BEGIN CERTIFICATE-----\n\
MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh\n\
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n\
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH\n\
MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT\n\
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n\
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG\n\
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI\n\
2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx\n\
1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ\n\
q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz\n\
tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ\n\
vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP\n\
BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV\n\
5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY\n\
1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4\n\
NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG\n\
Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91\n\
8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe\n\
pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl\n\
MrY=\n\
-----END CERTIFICATE-----\n";




Http::Http(/* args */)
{
}

Http::~Http()
{

}




int setUpWiFi()
{
    if (isWiFiConnected())
    {  
        
        return 0;
    }
   
   String ssid = getSsid();
   String password = getPassword();
 
    if (ssid.isEmpty())
    {
        Serial.println("ssid 为空");
        light("r", true);
        return 2;
    }
    if (password.isEmpty())
    {
        Serial.println("password 为空");
       // light("r", true);
        return 3;
    }
    Serial.println(ssid);
    Serial.println(password);

    WiFi.setAutoReconnect(true);
  

    String deviceId = getEspId();
    String number = deviceId.substring(deviceId.length() - 4);
    String hostname = "SmartCat_" + number;

    WiFi.setHostname(hostname.c_str());
    if (isDev())
    {
        // WiFi.config(local_IP, gateway, subnet, dns1);
    }

    wifi.addAP(ssid.c_str(), password.c_str());
    Serial.print("Waiting for WiFi... ");
    count = 0;
    while (wifi.run() != WL_CONNECTED)
    {
        Serial.print(".");
        delay(500);
        count++;
        if (count >= 2)
        {
            count = 0;
           // light("r", true);
            return 4;
        }
    }
    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("localIP address: ");
    Serial.println(WiFi.localIP());
 
    long time = isDev() ? 60 * 60 * 24 : 60 * 10;
   // blink("g", time);
    setWiFiConnected(true);
    // setClock1();
    // randomSeed(analogRead(1));
    return 0;
}


String getWiFiLocalIP(){

  IPAddress ipaddr_addr = WiFi.localIP();
   
   return  ipaddr_addr.toString();
}


void setClock1() {
  configTime(0, 0, "pool.ntp.org");

  Serial.print(F("Waiting for NTP time sync: "));
  time_t nowSecs = time(nullptr);
  while (nowSecs < 8 * 3600 * 2) {
    delay(500);
    Serial.print(F("."));
    yield();
    nowSecs = time(nullptr);
  }

  Serial.println();
  struct tm timeinfo;
  gmtime_r(&nowSecs, &timeinfo);
  Serial.print(F("Current time: "));
  Serial.print(asctime(&timeinfo));
}


 

void requestGets()
{
    if (wifi.run() == WL_CONNECTED)
    {
        WiFiClient client;
        HTTPClient http;
      
     
        Serial.print("[HTTP] begin...\n");

       
        if (http.begin(client, "https://www.smartlinked.cn",443,"/test/hello",true))
        {
            Serial.print("[HTTP] GET...\n");
            // start connection and send HTTP header
            int httpCode = http.GET();
            

            // httpCode will be negative on error
            if (httpCode > 0)
            {
                // HTTP header has been send and Server response header has been handled
                Serial.printf("[HTTP] GET... code: %d\n", httpCode);
                // file found at server
                if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY)
                {
                    String payload = http.getString();
                    Serial.println(payload);
                }
            }
            else
            {
                Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
            }
            http.end();
        }
        else
        {
            Serial.println("[HTTP] Unable to connect");
        }
    }
}

// void requestPost2(){
//      NetworkClientSecure *client = new NetworkClientSecure;
//   if (client) {
//     client->setCACert(rootCACertificate);

//     {
//       // Add a scoping block for HTTPClient https to make sure it is destroyed before NetworkClientSecure *client is
//       HTTPClient https;

//       Serial.print("[HTTPS] begin...\n");
//       if (https.begin(*client, "https://jigsaw.w3.org/HTTP/connection.html")) {  // HTTPS
//         Serial.print("[HTTPS] GET...\n");
//         // start connection and send HTTP header
//         int httpCode = https.GET();

//         // httpCode will be negative on error
//         if (httpCode > 0) {
//           // HTTP header has been send and Server response header has been handled
//           Serial.printf("[HTTPS] GET... code: %d\n", httpCode);

//           // file found at server
//           if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
//             String payload = https.getString();
//             Serial.println(payload);
//           }
//         } else {
//           Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
//         }

//         https.end();
//       } else {
//         Serial.printf("[HTTPS] Unable to connect\n");
//       }

//       // End extra scoping block
//     }

//     delete client;
//   } else {
//     Serial.println("Unable to create client");
//   }

//   Serial.println();
//   Serial.println("Waiting 10s before the next round...");
//   delay(10000);
// }


static int failedCount=0;



int requestPost(String url, String msg, HttpCallBack callback)
{

    // if(isAdvertising()){
    //     return;
    // }

//    if (isPumpContinue())
//    {
//        Http http;
//        http.setUrl(url);
//        http.setData(msg);
//        http.setHttpCallBack(callback);
//        addCachePost(http);
//        return;
//    }

  if(!isWiFiConnected()){
    return -1;
  }
    // wait for WiFi connection
    if ((wifi.run() == WL_CONNECTED))
    {

        HTTPClient http;

        Serial.print("[HTTP] begin...\n");
        // configure traged server and url
        //  http.begin("https://www.howsmyssl.com/a/check"); // HTTPS
        Serial.println(url);
    //     if(isDev()){
    //   http.begin(url);
    //     }else{
    //           http.begin(url,ca);   
          
    //     }
        http.begin(url);
        http.addHeader("Content-Type", "application/json");
        http.setTimeout(5000);
       
        Preferences preferences;
        preferences.begin("my-app", false);
        if (preferences.isKey("token"))
        {
            String token = preferences.getString("token", "");
            http.addHeader("token", token);
        }

        int httpCode = http.POST(msg);

        if (httpCode > 0)
        {
            Serial.printf("[HTTP] POST... code: %d\n", httpCode);
            if (httpCode == HTTP_CODE_OK)
            {
                Serial.printf("[ HTTP_CODE_OK: %d\n", httpCode);
                String payload = http.getString();
                // Serial.println(payload);
                if(callback!=nullptr){
                     callback(payload);
                }
              
            }

            setSendDataFailed(false);
            return 0;
        }
        else
        {
            Serial.printf("[HTTP] POST... failed, error: %s\n", http.errorToString(httpCode).c_str());
            failedCount++;

            setSendDataFailed(true);
            if(failedCount>=3){
                failedCount=0;
                setWiFiConnected(false);
                setUpWiFi();
            }
            putLog(POST_FAIL,getRtcTime().getEpoch(),"");
            return -2;
        }

        http.end();
    }
    return -3;
}

void requestPost1(String url, String msg, HttpCallBack callback, HttpCallBack error)
{
    //  if(isAdvertising()){
    //     return;
    // }//激活时不需要过滤
    // wait for WiFi connection
    if ((wifi.run() == WL_CONNECTED))
    {
        HTTPClient http;
        Serial.print("[HTTP] begin...\n");
        // configure traged server and url
        //  http.begin("https://www.howsmyssl.com/a/check"); // HTTPS
        Serial.println(url);
         
         http.begin(url);
        
        http.addHeader("Content-Type", "application/json");
        Preferences preferences;
        preferences.begin("my-app", false);
        if (preferences.isKey("token"))
        {
            String token = preferences.getString("token", "");
            http.addHeader("token", token);
        }

        int httpCode = http.POST(msg);
        if (httpCode > 0)
        {
            Serial.printf("[HTTP] POST... code: %d\n", httpCode);
            if (httpCode == HTTP_CODE_OK)
            {
                Serial.printf("[ HTTP_CODE_OK: %d\n", httpCode);
                String payload = http.getString();
                Serial.println(payload);
                callback(payload);
            }
        }
        else
        {
            const char *err = http.errorToString(httpCode).c_str();
            Serial.printf("[HTTP] POST... failed, error: %s\n", err);
            if (error != nullptr)
            {
                Serial.println("错误回调：");
                Serial.println(http.errorToString(httpCode));
                error(http.errorToString(httpCode));
            }
        }

        http.end();
    }
}

void requestGet()
{
    if (wifi.run() == WL_CONNECTED)
    {
        WiFiClient client;
        HTTPClient http;
        
        Serial.print("[HTTP] begin...\n");
        if (http.begin(client, "http://www.smartlinked.cn:8088/test/hello"))
        {
            Serial.print("[HTTP] GET...\n");
            // start connection and send HTTP header
            int httpCode = http.GET();
            // httpCode will be negative on error
            if (httpCode > 0)
            {
                // HTTP header has been send and Server response header has been handled
                Serial.printf("[HTTP] GET... code: %d\n", httpCode);
                // file found at server
                if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY)
                {
                    String payload = http.getString();
                    Serial.println(payload);
                }
            }
            else
            {
                Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
            }
            http.end();
        }
        else
        {
            Serial.println("[HTTP] Unable to connect");
        }
    }
}


void testHttps(){

esp_random();
  WiFiClientSecure *client = new WiFiClientSecure;
  if (client) {
   // client->setInsecure();
    client->setCACert(ca);
    {
      // Add a scoping block for HTTPClient https to make sure it is destroyed before NetworkClientSecure *client is
      HTTPClient https;

      Serial.print("[HTTPS] begin...\n");
      esp_random();
      if (https.begin(*client, "https://www.smartlinked.cn/test/hello")) {  // HTTPS
        Serial.print("[HTTPS] GET...\n");
        // start connection and send HTTP header
        int httpCode = https.GET();

        // httpCode will be negative on error
        if (httpCode > 0) {
          // HTTP header has been send and Server response header has been handled
          Serial.printf("[HTTPS] GET... code: %d\n", httpCode);

          // file found at server
          if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
            String payload = https.getString();
            Serial.println(payload);
          }
        } else {
          Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
        }

        https.end();
      } else {
        Serial.printf("[HTTPS] Unable to connect\n");
      }

      // End extra scoping block
    }

    delete client;
  } else {
    Serial.println("Unable to create client");
  }

  Serial.println();
  Serial.println("Waiting 10s before the next round...");

}



void sendCachePost(){
    if(isPumpContinue()){
        return;
    }
    if(cacheHttpList.isEmpty()){
        return;
    }
    cacheHttpList.forEach([](Http& http){
         requestPost(http);
    });

    cacheHttpList.clear();
}

void  addCachePost(Http http){

    cacheHttpList.add(http);
}

void requestPost(Http http){

    int ret =  requestPost(http.getUrl(),http.getData(),http.getHttpCallBack());

   // if(getAppMode()==2){
        if(ret==-2){//如果请求失败，比如超时，再请求一次
             ret =  requestPost(http.getUrl(),http.getData(),http.getHttpCallBack());
        }
   // }
   
}
 